﻿/*
 * Please leave this Copyright notice in your code if you use it
 * Written by Decebal Mihailescu [http://www.codeproject.com/script/articles/list_articles.asp?userid=634640]
 */
namespace SubTitleConvertors
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using CommonUtils;
    using System.ComponentModel.Composition;
    using System.IO;
    using System.Text.RegularExpressions;

    [Export(typeof(ITextImport))]
    [ExportMetadata("SpecialFormat", true)]
    [ExportMetadata("Description", "Sub text subtitle files")]
    [ExportMetadata("FileExtension", "*.sub")]
    [ExportMetadata("ContextMenuText", "&Translate")]
    [ExportMetadata("IconName", @"internet.ico")]
    public class SubFileReader : ITextImport, ITextManipulation
    {

        #region Imports
        [Import("WebSite")]
        public string _strWebSite;
        [Import("SubLogoFormat")]
        public string _LogoFormat;
        #endregion
        #region ITextImport Members


        public string GetAllTextFromFile(string fileName, out Encoding encoding)
        {
            if (string.IsNullOrEmpty(fileName))
            {
                throw new ArgumentException(null, "fileName");
            }
            if (!File.Exists(fileName))
            {
                throw new ArgumentException("File '" + fileName + "' is not found");
            }
            string str = string.Empty;
            try
            {
                var arg = new ProgressEventArgs();
                arg.Description = "Opening sub file";
                arg.Progress = 0;
                if (ProgressChanged != null && ProgressChanged.GetInvocationList().Length > 0)
                    ProgressChanged(this, arg);
                Encoding encoding_guessed = EncodingEx.GetFileEncoding(fileName);
                string txt = null;
                using (StreamReader reader = new StreamReader(fileName, true))//GetEncoding(0x4e3)))
                {
                    txt = reader.ReadToEnd();
                    encoding = reader.CurrentEncoding;
                }
                txt = txt.FixEoL();
                List<string[]> lst = ((ITextManipulation)this).GetSplitedText(txt) as List<string[]>;
                //try the encoding_guessed if failed
                if (lst.Count <= 0 && encoding_guessed != encoding)
                {
                    using (StreamReader reader = new StreamReader(fileName, encoding_guessed))
                    {
                        txt = reader.ReadToEnd();
                        encoding = reader.CurrentEncoding;
                    }
                    txt = txt.FixEoL();
                }
                int len = txt.Length;
                lst = ((ITextManipulation)this).GetSplitedText(txt) as List<string[]>;
                if (lst[0][1].IndexOf(_strWebSite, StringComparison.InvariantCultureIgnoreCase) == -1)
                    len += AddFLTTitle(lst);
                else if (lst[0][1].IndexOf(_strWebSite, StringComparison.InvariantCultureIgnoreCase) > 0)
                {
                    lst[0][1] = _strWebSite + "\r\n";
                    len += _strWebSite.Length + 1;

                }
                StringBuilder sb = new StringBuilder(len + 10);
                lst.ForEach(sub => { sb.Append(sub[0]); sb.Append(sub[1]); });
                txt = sb.ToString();
                return txt;
            }
            catch (Exception exception)
            {
                throw new Exception("Error during text extraction from Text-file: " + fileName + Environment.NewLine + exception.Message);
            }

        }

        private int AddFLTTitle(List<string[]> lst)
        {
            try
            {

                Match m = _times.Match(lst[0][0]);
                int firstFrame = Convert.ToInt32(m.Groups["Begin"].ToString());
                string[] myentrtry = new string[2];
                if (firstFrame < 750)
                {
                    myentrtry[0] = string.Format("{2}{0}{3}{2}{1}{3}", firstFrame / 5, firstFrame / 5 * 4, '{', '}');
                }
                else
                {
                    myentrtry[0] = string.Format("{2}{0}{3}{2}{1}{3}", firstFrame / 3, firstFrame / 3 * 2, '{', '}');
                }
                myentrtry[1] = _strWebSite + "\r\n";
                lst.Insert(0, myentrtry);
                return myentrtry[0].Length + myentrtry[1].Length;

            }
            catch (Exception ex)
            {

                return 0;
            }

        }
        public event EventHandler ProgressChanged;


        private bool ShowProgress(string desc, int progress)
        {
            var arg = new ProgressEventArgs();
            arg.Description = desc;
            arg.Progress = progress;
            if (ProgressChanged != null && ProgressChanged.GetInvocationList().Length > 0)
            {
                ProgressChanged(this, arg);
                return true;
            }
            else
                return false;

        }

        private static string[] FragmentFromMatch(Match match)
        {
            string[] sub = new string[2];
            sub[0] = string.Format("{2}{0}{3}{2}{1}{3}", match.Groups["Begin"], match.Groups["End"], '{', '}');
            sub[1] = match.Groups["Text"].ToString();
            if (!sub[1].EndsWith("\r\n"))
                sub[1] += "\r\n";
            return sub;
        }
        #endregion

        private readonly Regex _fragmentsRegex =
                new Regex(@"[ \t]*\{[ \t]*(?<Begin>(?:[0-9]+))[ \t]*\}[ \t]*[ \t]*\{[ \t]*(?<End>(?:[0-9]+))[ \t]*\}[ \t]*(?<Text>(?:[^\{\r\n]+))[\r\n]*", RegexOptions.Compiled | RegexOptions.Multiline);
        Regex _zeroTitle =
            new Regex(@"^[ \t]*[0]+[ \t]*\r\n[ \t]*([0-9]{2}[\:]){2}[0-9]{2}[,][0-9]{3}[ \t]*-->[ \t]*([0-9]{2}[\:]){2}[0-9]{2}[,][0-9]{3}[ \t]*\r\n", RegexOptions.Compiled);
        Regex _times =
            new Regex(@"[ \t]*\{[ \t]*(?<Begin>(?:[0-9]+))[ \t]*\}[ \t]*[ \t]*\{[ \t]*(?<End>(?:[0-9]+))[ \t]*\}[ \t]*", RegexOptions.Compiled | RegexOptions.Multiline);

        #region ITextManipulation Members

        string ITextManipulation.PreTranslation(string frg)
        {
            return frg.Replace("\r\n", "<br><br>").Replace("|", "<br>");
        }

        string ITextManipulation.PostTranslation(string frg)
        {
            return frg.Replace("\r\n", "|");
        }

        IList<string[]> ITextManipulation.GetSplitedText(string text)
        {
            string str = string.Empty;
            try
            {
                var arg = ShowProgress("Opening sub file", 0);

                MatchCollection matches = _fragmentsRegex.Matches(text);
                List<string[]> fragments = matches.OfType<Match>().Select((Match match, int i) => { if (i != 0 && i % 200 == 0) ShowProgress("...", i * 100 / matches.Count); return FragmentFromMatch(match); }).ToList();
                ShowProgress("Sub file Opened", 100);
                return fragments;
            }
            catch (Exception exception)
            {
                return null;
            }
        }

        string ITextManipulation.LogoFormat
        {
            get { return _LogoFormat; }
        }

        #endregion
    }
}

